﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SimpleRest.Tools.Scaffolding
{
    public class ObjectAssociationGraph<T>
    {
        public ObjectAssociationGraph()
        {
            this.MasterList = new List<ObjectAssociationNode<T>>();
        }
        public ObjectAssociationGraph(Type type)
            : this()
        {
            this.InitialType = type;
        }

        private List<ObjectAssociationNode<T>> MasterList { get; set; }

        private readonly Type InitialType;

        public List<T> GetAllChildren(T obj)
        {
            List<T> items = new List<T>();

            foreach (ObjectAssociationNode<T> item in this.MasterList)
                if (item.TargetNode.Equals(obj) && item.Weight == ObjectAssociationNode<T>.WeightType.Child && item.DestinationNode != null)
                    items.Add(item.DestinationNode);
                else if (item.DestinationNode != null && item.DestinationNode.Equals(obj) && item.Weight == ObjectAssociationNode<T>.WeightType.Parent)
                    items.Add(item.TargetNode);

            return items;
        }
        public List<T> GetParents(T obj)
        {
            List<T> items = new List<T>();

            foreach (ObjectAssociationNode<T> item in this.MasterList)
                if (item.TargetNode.Equals(obj) && item.Weight == ObjectAssociationNode<T>.WeightType.Parent && item.DestinationNode != null)
                    items.Add(item.DestinationNode);
                else if (item.DestinationNode != null && item.DestinationNode.Equals(obj) && item.Weight == ObjectAssociationNode<T>.WeightType.Child)
                    items.Add(item.TargetNode);

            return items;
        }
        public List<T> GetUniqueItems()
        {
            List<T> items = new List<T>();

            foreach (var item in this.MasterList)
            {
                if (!items.Contains(item.TargetNode))
                {
                    items.Add(item.TargetNode);
                }
                if (item.DestinationNode != null && !items.Contains(item.DestinationNode))
                    items.Add(item.DestinationNode);
            }
            return items;
        }

        public bool Add(ObjectAssociationNode<T> node)
        {
            if (node.TargetNode == null)
                return false;

            if (!this.MasterList.Contains(node))
            {
                this.MasterList.Add(node);
                return true;
            }
            return false;
        }
    }

    public class ObjectAssociationNode<T>
    {
        public WeightType Weight { get; set; }

        public T TargetNode { get; set; }
        public T DestinationNode { get; set; }

        public enum WeightType{
            Parent,
            Child
        }
        
        private bool Equals(ObjectAssociationNode<T> item)
        {
            if (item == null)
                return false;

            if (item.TargetNode as object == this.TargetNode as object && this.DestinationNode as object == item.DestinationNode as object && item.Weight == this.Weight)
                return true;
            return false;
        }

        public override bool Equals(object obj)
        {
            return this.Equals(obj as ObjectAssociationNode<T>);
        }
    }
}
